﻿using Common.Msg;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Net;
using System.Text;
using System.Linq;

namespace Common.Http
{
    public class HttpHelper
    {
        /// <summary>
        /// 根据url下载内容(GBK)
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public static string GetByGBK(string url, IDictionary<string, string> parameters = null)
        {
            return Get(url, Encoding.GetEncoding("GBK"), parameters);
        }
        /// <summary>
        /// 根据url下载内容(GB2312)
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public static string GetByGB2312(string url, IDictionary<string, string> parameters = null)
        {
            return Get(url, Encoding.GetEncoding("GB2312"), parameters);
        }


        /// <summary>
        /// 根据url下载内容(UTF8)
        /// </summary>
        /// <param name="strUrl"></param>
        /// <param name="dicParams"></param>
        /// <param name="headers">为空时默认text/html; charset=utf-8</param>
        /// <param name="dicHeaders"></param>
        /// <returns></returns>
        public static string Get(string strUrl, IDictionary<string, string> dicParams = null, HttpHeaders headers = null, IDictionary<string, string> dicHeaders = null)
        {
            if (headers == null)
            {
                headers = new HttpHeaders()
                {
                    timeout = 30 * 1000,
                    userAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36",
                    contentType = "text/html; charset=utf-8"// "text/html;charset=gbk";//
                };
            }
            return Get(strUrl, Encoding.UTF8, dicParams, headers, dicHeaders);
        }
        public static string Get(string strUrl, Encoding encode, IDictionary<string, string> dicParams = null, HttpHeaders headers = null, IDictionary<string, string> dicHeaders = null)
        {
            strUrl += "?" + string.Join("&", dicParams.Select(s => s.Key + "=" + s.Value));
            var webRequest = CreateHttpWebRequest(strUrl, headers);
            foreach (KeyValuePair<string, string> item in dicHeaders)
            {
                if (string.IsNullOrWhiteSpace(item.Key) == false && string.IsNullOrWhiteSpace(item.Value) == false)
                    webRequest.Headers.Add(item.Key, item.Value);
            }
            webRequest.Method = "Get";
            return RequestWeb(webRequest, encode);
        }
        public static string Get(HttpWebRequest webRequest, Encoding encode)
        {
            webRequest.Method = "Get";
            return RequestWeb(webRequest, encode);
        }
        public static string Post(string strUrl, IDictionary<string, string> dicParams = null, HttpHeaders headers = null, IDictionary<string, string> dicHeaders = null)
        {
            var webRequest = CreateHttpWebRequest(strUrl, headers);

            foreach (KeyValuePair<string, string> item in dicHeaders)
            {
                if (string.IsNullOrWhiteSpace(item.Key) == false && string.IsNullOrWhiteSpace(item.Value) == false)
                    webRequest.Headers.Add(item.Key, item.Value);
            }
            return Post(webRequest, Encoding.UTF8, dicParams);
        }
        public static string Post(string strUrl, Encoding encode, IDictionary<string, string> dicParams = null, HttpHeaders headers = null, IDictionary<string, string> dicHeaders = null)
        {
            var webRequest = CreateHttpWebRequest(strUrl, headers);

            foreach (KeyValuePair<string, string> item in dicHeaders)
            {
                if (string.IsNullOrWhiteSpace(item.Key) == false && string.IsNullOrWhiteSpace(item.Value) == false)
                    webRequest.Headers.Add(item.Key, item.Value);
            }
            return Post(webRequest, encode, dicParams);
        }
        public static string Post(HttpWebRequest webRequest, Encoding encode, IDictionary<string, string> dicParams = null)
        {
            webRequest.Method = "POST";
            if (dicParams != null && dicParams.Count > 0)
            {
                byte[] data = encode.GetBytes(string.Join("&", dicParams.Select(s => s.Key + "=" + s.Value)));
                using (Stream stream = webRequest.GetRequestStream())
                {
                    stream.Write(data, 0, data.Length);
                }
            }
            return RequestWeb(webRequest, encode);
        }
        private static string RequestWeb(HttpWebRequest webRequest, Encoding encode)
        {
            string html = string.Empty;
            using (HttpWebResponse response = webRequest.GetResponse() as HttpWebResponse)//发起请求
            {
                if (response.StatusCode != HttpStatusCode.OK)
                {
                   Log.GetLog.Warn("url请求报错", typeof(HttpHelper));
                }
                else
                {
                    try
                    {
                        StreamReader sr = null;
                        if (response.ContentEncoding.ToLower() == "gzip")
                        {
                            MemoryStream ms = GZipDecompress(response.GetResponseStream());
                            sr = new StreamReader(ms, encode);
                        }
                        else
                        {
                            sr = new StreamReader(response.GetResponseStream(), encode);
                        }
                        html = sr.ReadToEnd();//读取数据
                        sr.Close();
                    }
                    catch (Exception ex)
                    {
                        Log.GetLog.Error("url请求异常。", typeof(HttpHelper), ex);
                        html = null;
                    }
                }
            }
            return html;
        }

        public static HttpWebRequest CreateHttpWebRequest(string url, HttpHeaders headers)
        {
            HttpWebRequest request = HttpWebRequest.Create(CheckUrlHttp(url)) as HttpWebRequest;//模拟请求
            if (headers != null)
            {
                if (headers.timeout > 0)
                    request.Timeout = headers.timeout;//设置30s的超时
                else
                    request.Timeout = 30 * 1000;//设置30s的超时

                if (string.IsNullOrEmpty(headers.userAgent))
                    request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.86 Safari/537.36";
                else
                    request.UserAgent = headers.userAgent;

                if (string.IsNullOrEmpty(headers.contentType))
                    request.ContentType = "text/html; charset=utf-8";// "text/html;charset=gbk";//
                else
                    request.ContentType = headers.contentType;

                if (string.IsNullOrEmpty(headers.accept) == false)
                    request.Accept = headers.accept;
                if (string.IsNullOrEmpty(headers.connection) == false)
                    HttpHelper.SetHeaderValue(request.Headers, "Connection", headers.connection);
                if (string.IsNullOrEmpty(headers.host) == false)
                    request.Host = headers.host;
                if (string.IsNullOrEmpty(headers.referer) == false)
                    request.Referer = headers.referer;
            }
            return request;
        }
        public static HttpWebRequest CreateHttpWebRequest(string url, int timeout = 0, string strCookie = null, string contentType = null, string host = null, string accept = null, string acceptEncoding = null, string acceptLanguage = null, string cacheControl = null, string connection = null, string referer = null, string userAgent = null, string upgradeInsecureRequests = null, string xRequestedWith = null, string origin = null)
        {
            HttpWebRequest request = HttpWebRequest.Create(CheckUrlHttp(url)) as HttpWebRequest;//模拟请求
            if (timeout > 0)
                request.Timeout = timeout;//设置30s的超时
            else
                request.Timeout = 30 * 1000;//设置30s的超时

            if (string.IsNullOrEmpty(userAgent))
                request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.86 Safari/537.36";
            else
                request.UserAgent = userAgent;

            if (string.IsNullOrEmpty(contentType))
                request.ContentType = "text/html; charset=utf-8";// "text/html;charset=gbk";//
            else
                request.ContentType = contentType;

            if (string.IsNullOrEmpty(accept) == false)
                request.Accept = accept;
            if (string.IsNullOrEmpty(acceptEncoding) == false)
                request.Headers.Add("Accept-Encoding", acceptEncoding);
            if (string.IsNullOrEmpty(acceptLanguage) == false)
                request.Headers.Add("Accept-Language", acceptLanguage);
            if (string.IsNullOrEmpty(cacheControl) == false)
                request.Headers.Add("Cache-Control", cacheControl);
            if (string.IsNullOrEmpty(connection) == false)
                HttpHelper.SetHeaderValue(request.Headers, "Connection", connection);
            if (string.IsNullOrEmpty(strCookie) == false)
                request.Headers.Add("Cookie", strCookie);
            if (string.IsNullOrEmpty(host) == false)
                request.Host = host;
            if (string.IsNullOrEmpty(upgradeInsecureRequests) == false)
                request.Headers.Add("Upgrade-Insecure-Requests", upgradeInsecureRequests);
            if (string.IsNullOrEmpty(referer) == false)
                request.Referer = referer;
            if (string.IsNullOrEmpty(xRequestedWith) == false)
                request.Headers.Add("X-Requested-With", xRequestedWith);
            if (string.IsNullOrEmpty(origin) == false)
                request.Headers.Add("Origin", origin);
            return request;
        }
        /// <summary>
        /// 设置HTTP头
        /// </summary>
        /// <param name="header"></param>
        /// <param name="name"></param>
        /// <param name="value"></param>
        public static void SetHeaderValue(WebHeaderCollection header, string name, string value)
        {
            var property = typeof(WebHeaderCollection).GetProperty("InnerCollection",
                System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
            if (property != null)
            {
                var collection = property.GetValue(header, null) as System.Collections.Specialized.NameValueCollection;
                collection[name] = value;
            }
        }
        /// <summary>
        /// 压缩为gzip格式的字节
        /// </summary>
        /// <param name="bytes"></param>
        /// <returns></returns>
        public static byte[] GZipCompressBytes(byte[] bytes)
        {
            using (MemoryStream compressStream = new MemoryStream())
            {
                using (var zipStream = new GZipStream(compressStream, CompressionMode.Compress))
                    zipStream.Write(bytes, 0, bytes.Length);
                return compressStream.ToArray();
            }
        }
        /// <summary>
        /// 解压缩gzip格式的字节
        /// </summary>
        /// <param name="bytes"></param>
        /// <returns></returns>
        public static byte[] GZipDecompress(byte[] bytes)
        {
            using (var compressStream = new MemoryStream(bytes))
            {
                using (var zipStream = new GZipStream(compressStream, CompressionMode.Decompress))
                {
                    using (var resultStream = new MemoryStream())
                    {
                        zipStream.CopyTo(resultStream);
                        return resultStream.ToArray();
                    }
                }
            }
        }
        /// <summary>
        /// 解压缩gzip格式的数据流
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static MemoryStream GZipDecompress(Stream stream)
        {
            using (var zipStream = new GZipStream(stream, CompressionMode.Decompress))
            {
                var resultStream = new MemoryStream();
                zipStream.CopyTo(resultStream);
                resultStream.Position = 0;
                return resultStream;
            }
        }
        /// <summary>
        /// 检查Url地址格式
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public static string CheckUrlHttp(string url)
        {
            if (!url.StartsWith("http:") && !url.StartsWith("https:"))
            {
                if (!url.StartsWith("//") && !url.StartsWith("//"))
                    url = "http://" + url;
                else
                    url = "http:" + url;
            }
            return url;
        }
    }
}
